package stud.cp.user.plugins.designer;

import java.math.BigInteger;
import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;

import stud.cp.core.dbaccess.DAOException;
import stud.cp.core.plugins.PluginConst;
import stud.cp.core.plugins.PluginRouter;
import stud.cp.core.plugins.WrongPageRequest;
import stud.cp.user.dbaccess.ObjectDAO;
import stud.cp.user.dbaccess.OracleDAOFactory;
import stud.cp.user.dbaccess.ParametersDAO;
import stud.cp.user.valueobjects.*;

/**
 * Session Bean implementation class ProductPluginBean
 */
@Stateless
public class ProductPluginBean implements ProductPluginBeanLocal {

    private static final BigInteger STORE_TYPE_PROPERTY_TYPE_DEF_ID = new BigInteger("2");
    /**
     * Фабрика DAO классов.
     */
    private OracleDAOFactory oracleDAOFactory = null;
    /**
     * Логгер.
     */
    private static Logger logger = Logger.getLogger("ACPII");

    /**
     * Метод, выполняющий бизнес логику плагина.
     *
     * @param req Реквест.
     * @return Класс плагин.
     */
    @Override
    public PluginRouter perform(HttpServletRequest req) {
        String subaction = req.getParameter(PluginConst.SUBACTION);


        if ((subaction != null) && (!subaction.equals(""))) {
            try {

                oracleDAOFactory = new OracleDAOFactory();
                oracleDAOFactory.initialize();
                /*
                 * Список действий которые могут выполниться.
                 */

                if (subaction.equals(PluginConst.GET_LIST)) {
                    return getListOfProducts(req);
                }

                /*
                 * Страница добавления
                 */
                if (subaction.equals(PluginConst.GET_ADD_PAGE)) {
                    return getAddPage(req);
                }

                /*
                 * Добавление новых данных
                 */
                if (subaction.equals(PluginConst.NEW_DATA)) {
                    return newData(req);
                }

                /*
                 * Страница редактирования
                 */
                if (subaction.equals(PluginConst.GET_EDIT_PAGE)) {
                    return getEditPage(req);
                }

                /*
                 * Сохранение измененных данных
                 */
                if (subaction.equals(PluginConst.SAVE_DATA)) {
                    return saveData(req);
                }

                /*
                 * Страница удаления
                 */
                if (subaction.equals(PluginConst.GET_DELETE_PAGE)) {
                    return getDeletePage(req);
                }
                
                

                /*
                 * Удаление данные
                 */
                if (subaction.equals(PluginConst.DELETE_DATA)) {
                    return deleteData(req);
                }

                if (subaction.equals(PluginConst.TEMPORARY_DELETE)) {
                    return temporaryDeleteData(req);
                }
                
                /*
                 * Страница просмотра данных о типе оружия
                 */
                if (subaction.equals(PluginConst.GET_VIEW_PAGE)) {
                    return getViewPage(req);
                }
                //
                //                /*Страница со списком свойств, принадлежащий данному типу оружия.*/
                //                if (subaction.equals(PluginConst.GET_WEAPON_TYPE_PROPERTIES_LIST)) {
                //                    return getObjectTypePropertyListPage(req);
                //                }
                //
                //                /*Страница с диалогом для пользователя, который хочет исключить свойство из типа оружия.*/
                //                if (subaction.equals(PluginConst.EXCLUDE_PROPERTY_FROM_WEAPON_TYPE_PAGE)) {
                //                    return getExcludePropertyFromObjectTypePage(req);
                //                }
                //
                //                /*Исключение свойства из объектного типа.*/
                //                if (subaction.equals(PluginConst.EXCLUDE_PROPERTY_FROM_WEAPON_TYPE)) {
                //                    return excludePropertyFromObjectType(req);
                //                }
                //
                //                /*Страница добавления свойств к типу оружия.*/
                //                if (subaction.equals(PluginConst.ADD_PROPERTIES_TO_WEAPON_TYPE_PAGE)) {
                //                    return getAddPropertiesToObjectTypePage(req);
                //                }
                //
                //                /*Добавление свойств к объектному типу*/
                //                if (subaction.equals(PluginConst.ADD_PROPERTIES_TO_WEAPON_TYPE)) {
                //                    return addPropertiesToObjectType(req);
                //                }

                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Действия для данного типа поддействия не найдено. Тип поддействия = " + subaction);
            } catch (DAOException ex) {
                logger.debug("Error due access to database. "
                        + "Plugin = ProductTypesPluginBean. "
                        + "Subaction=" + subaction, ex);
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Ошибка доступа к базе данных " + ex.getMessage());
            } catch (WrongPageRequest ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Данные из реквеста ошибочны :\n" + ex.getMessage());
            } catch (NumberFormatException ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "ID объекта не имеет числовой формат :\n" + ex.getMessage());
            } finally {

                if (oracleDAOFactory != null) {
                    try {
                        oracleDAOFactory.cleanUp();
                    } catch (DAOException ex) {
                        logger.debug("Error due access to database. "
                                + "Plugin = ProductTypesPluginBean. "
                                + "Subaction=" + subaction, ex);
                        req.setAttribute(PluginConst.ERROR_MESSAGE,
                                "Ошибка доступа к базе данных " + ex.getMessage());
                    }
                }
            }
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE,
                    "Тип поддействия не задан.");
        }

        return new PluginRouter("/errorpage.jsp");
    }

    private PluginRouter getListOfProducts(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);
        } else {
            throw new WrongPageRequest("Тип блюда с таким id=" + objectTypeId + " не существует. ");
        }

        List<DBObject> listOfDBObjects =
                oracleDAOFactory.getObjectDAO().getAllObjectByObjectTypeButNotDelete(objectTypeId);
        req.setAttribute(PluginConst.OBJECT_LIST, listOfDBObjects);
        return new PluginRouter("/Designer/Products/ProductsTable.jsp");
    }

    private PluginRouter getAddPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);
        } else {
            throw new WrongPageRequest("Тип блюда с таким id=" + objectTypeId + " не существует. ");
        }

        List<PropertyListValue> listOfStoreType =
                oracleDAOFactory.getPropertyListValuesDAO().getAllForListValueDef(STORE_TYPE_PROPERTY_TYPE_DEF_ID);
        req.setAttribute(PluginConst.STORE_TYPE_LIST, listOfStoreType);

        return new PluginRouter("/Designer/Products/AddProduct.jsp");
    }

    /**
     * Метод, позволяющий добавлять новые данные.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter newData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String name = req.getParameter(PluginConst.OBJECT_NAME);
        String description = req.getParameter(PluginConst.OBJECT_DESCRIPTION);
        String cost = req.getParameter(PluginConst.COST);
        String storeTypeListValueId = req.getParameter(PluginConst.STORE_TYPE);

        String objectTypeIdValue = req.getParameter(PluginConst.OBJECT_TYPE_ID);
        if ((objectTypeIdValue == null) || (objectTypeIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        BigInteger objectTypeId =
                new BigInteger(objectTypeIdValue);

        DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(objectTypeId);
        if (objectType != null) {
            BigInteger object_id =
                    oracleDAOFactory.getObjectDAO().
                    create(new DBObject(objectType.getObject_type_id(), name, description));
            ParametersDAO propertyValueDAO = oracleDAOFactory.getParameterDAO();

            propertyValueDAO.create(new Parameter(PluginConst.COST_PROPERTY_ID, cost, object_id, null));
            propertyValueDAO.create(new Parameter(PluginConst.STORE_TYPE_PROPERTY_ID, "0", object_id, new BigInteger(storeTypeListValueId)));

            //TODO::[High] добавить код, которые переносит данные в историю.
        } else {
            throw new WrongPageRequest("Тип продукта с таким id=" + objectTypeId + " не существует. ");
        }

        return new PluginRouter("products-action.do"
                + "?"
                + PluginConst.SUBACTION
                + "="
                + PluginConst.GET_LIST
                + "&"
                + PluginConst.OBJECT_TYPE_ID
                + "="
                + objectType.getObject_type_id(), false);
    }

    /**
     * Метод, который позволяет перейти на страницу удаления элемента.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getDeletePage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);
        if (object != null) {
            
            String errorMessage="";
            ObjectDAO objectDAO=oracleDAOFactory.getObjectDAO();
            DBObject dbObject;
            
            List<DBObjectReference> listOfReferenceOnObject=oracleDAOFactory.getObjectReferencesDAO().
                    getAllReferenceOnObjectWithPropertyIDButNotNull(objectId,PluginConst.LINK_ON_PRODUCT_PRODPERTY_ID);
            if(listOfReferenceOnObject.size()!=0){
                errorMessage+="Данный продукт находиться в рецепте следующих продуктов: <br/>";
                for(DBObjectReference referenceOnObject:listOfReferenceOnObject){
                    dbObject=objectDAO.getById(referenceOnObject.getObject_id());
                    errorMessage+=dbObject.getName()+"</br>";
                }
            }
            Parameter amountParam=oracleDAOFactory.getParameterDAO().getParameterByIdForObject(PluginConst.STORE_TYPE_PROPERTY_ID, objectId);
            if(Double.valueOf(amountParam.getValue())!=0){
                errorMessage+=("Для удаления продукта из списка его запас на складе должен равняться нулю, а не = "+amountParam.getValue()+".");
            }
            if(!errorMessage.equals("")){
                req.setAttribute(PluginConst.ERROR_MESSAGE, errorMessage);
            }
            req.setAttribute(PluginConst.OBJECT, object);
            return new PluginRouter("/Designer/Products/DeleteProduct.jsp");
        } else {
            throw new WrongPageRequest("Блюда с таким id=" + objectId + " не существует. ");
        }

    }

    /**
     * Метод, удаляющий данные из базы данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter deleteData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        if (object != null) {
            oracleDAOFactory.getObjectDAO().delete(object.getObject_id());
            return new PluginRouter("products-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST
                    + "&"
                    + PluginConst.OBJECT_TYPE_ID
                    + "="
                    + object.getObject_type_id(), false);
        } else {
            throw new WrongPageRequest("Блюда с таким id=" + objectId + " не существует. ");
        }

    }

    /**
     * Метод, который позволяет перейти на страницу редактирования данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getEditPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        if (object != null) {

            DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(object.getObject_type_id());
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);

            req.setAttribute(PluginConst.OBJECT, object);

            List<Parameter> parameterList = oracleDAOFactory.getParameterDAO().getPropertyValueForObject(objectId);

            for (Parameter param : parameterList) {
                if (param.getProperty_id().equals(PluginConst.COST_PROPERTY_ID)) {
                    req.setAttribute(PluginConst.COST_PARAMETER, param);
                }
                if (param.getProperty_id().equals(PluginConst.STORE_TYPE_PROPERTY_ID)) {
                    req.setAttribute(PluginConst.STORE_TYPE_PARAMETER, param);
                }
            }

//            List<PropertyListValue> listOfStoreType =
//                    oracleDAOFactory.getPropertyListValuesDAO().getAllForListValueDef(STORE_TYPE_PROPERTY_TYPE_DEF_ID);
//            req.setAttribute(PluginConst.STORE_TYPE_LIST, listOfStoreType);

            return new PluginRouter("/Designer/Products/EditProduct.jsp");
        } else {
            throw new WrongPageRequest("Блюдо с таким id=" + objectId + " не существует. ");
        }

    }

    /**
     * Сохранение данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter saveData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String name = req.getParameter(PluginConst.OBJECT_NAME);
        String description = req.getParameter(PluginConst.OBJECT_DESCRIPTION);
        String cost = req.getParameter(PluginConst.COST);
        String storeTypeListValueId = req.getParameter(PluginConst.STORE_TYPE);

        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не задан!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);

        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);
        if (object != null) {

            object.setName(name);
            object.setDescription(description);
            oracleDAOFactory.getObjectDAO().update(object);

            ParametersDAO propertyValueDAO = oracleDAOFactory.getParameterDAO();

            List<Parameter> parameterList = oracleDAOFactory.getParameterDAO().getPropertyValueForObject(objectId);

            for (Parameter param : parameterList) {
                if (param.getProperty_id().equals(PluginConst.COST_PROPERTY_ID)) {
                    param.setValue(cost);
                    propertyValueDAO.update(param);
                }
//                if (param.getProperty_id().equals(PluginConst.STORE_TYPE_PROPERTY_ID)) {
//                    param.setProperty_list_value_id(new BigInteger(storeTypeListValueId));
//                    propertyValueDAO.update(param);
//                }
            }

            //TODO::[High] добавить код, которые переносит данные в историю.
        } else {
            throw new WrongPageRequest("Блюдо с таким id=" + objectId + " не существует. ");
        }

        return new PluginRouter("products-action.do"
                + "?"
                + PluginConst.SUBACTION
                + "="
                + PluginConst.GET_VIEW_PAGE
                + "&"
                + PluginConst.OBJECT_ID
                + "="
                + object.getObject_id(), false);

    }

    private PluginRouter getViewPage(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        if (object != null) {

            DBObjectType objectType = oracleDAOFactory.getObjectTypesDAO().getById(object.getObject_type_id());
            req.setAttribute(PluginConst.OBJECT_TYPE, objectType);

            req.setAttribute(PluginConst.OBJECT, object);

            List<Parameter> parameterList = oracleDAOFactory.getParameterDAO().getPropertyValueForObject(objectId);

            for (Parameter param : parameterList) {
                if (param.getProperty_id().equals(PluginConst.COST_PROPERTY_ID)) {
                    req.setAttribute(PluginConst.COST_PARAMETER, param);
                }
                if (param.getProperty_id().equals(PluginConst.STORE_TYPE_PROPERTY_ID)) {
                    req.setAttribute(PluginConst.STORE_TYPE_PARAMETER, param);
                }
            }

            return new PluginRouter("/Designer/Products/ViewProduct.jsp");
        } else {
            throw new WrongPageRequest("Блюдо с таким id=" + objectId + " не существует. ");
        }
    }

    private PluginRouter temporaryDeleteData(HttpServletRequest req) throws WrongPageRequest, DAOException {
        String objectIdValue = req.getParameter(PluginConst.OBJECT_ID);
        if ((objectIdValue == null) || (objectIdValue.equals(""))) {
            throw new WrongPageRequest("ID объекта не занад!");
        }
        BigInteger objectId =
                new BigInteger(objectIdValue);
        DBObject object = oracleDAOFactory.getObjectDAO().getById(objectId);

        if (object != null) {     
            object.setName("[Удалено]"+object.getName());
            object.setIsDelete(Boolean.TRUE);
            oracleDAOFactory.getObjectDAO().update(object);
            return new PluginRouter("products-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST
                    + "&"
                    + PluginConst.OBJECT_TYPE_ID
                    + "="
                    + object.getObject_type_id(), false);
        } else {
            throw new WrongPageRequest("Блюда с таким id=" + objectId + " не существует. ");
        }

    }
}
